/*  iImager (network disk imaging via iscsi)
	Copyright (C) 2009-2010 Yao Wei <njustyw@gmail.com>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/


#ifndef QIMAGERTASK_H
#define QIMAGERTASK_H

#include "trimps_forensic_global.h"


class HDObject;
class RStatus;
class QReadThread;
class QVerifyThread;
class QWriteThread;
struct Q_MT_BUFFER;
struct Q_MT_PARAM;
struct ImagingOptionsStruct;

typedef struct RunningDisk
{
	QString filename;
	quint8 imagingType;
	quint8 hashType;
	ImagingTaskStatus runningState;
	struct Q_MT_PARAM* threadParam;
}RunningDisk;

/** The control center for hard disk imaging*/
class ImagerTask : public QObject
{
	Q_OBJECT
public:
	ImagerTask(QObject* parent = 0);
	~ImagerTask();

	/** 
	 Prepare some work before doing actual imaging taskManage including initialize the Ui of running status
	 @param obj the hard disk object
	 @param filename the imaging file that will be wrote to
	 @param imagingType the imaging type
	 @param hashType the hash type
	 @param caseNo the case number
	 @return false on failure, true otherwise
	*/
	bool readyForImaging(HDObject* obj, const QString& filename,  quint8 imagingType, 
						quint8 hashType, const QString& caseNo);

	/** Start to imaging hard disk */
	bool startImaging(HDObject* obj);
	bool pauseImaging(HDObject* obj);
	bool continueImaging(HDObject* obj);
	bool cancelImaging(HDObject* obj);

	/** Get the count of running taskManage for imaging */
	int countOfRunningTask()const;

public slots:

	/** these slot functions are available for reader's and writer's internal multithread */


	/** What will be done if corresponding drop copy signal emitted by the Write/Read/Verify thread */
	void dropImagingTask_MT(HDObject* obj, struct Q_MT_PARAM* param);
	
	/** What will be done when the Write/Read/Verify thread completed its taskManage*/
	void doneImagingTask_MT(HDObject* obj, double meanSpeed, int totalTime, struct Q_MT_PARAM* param);
	
	/** What will be done if error occured by the Write/Read/Verify thread */
	void showException_MT(HDObject* obj, char* msg, struct Q_MT_PARAM* param);
	
	/** Update the status of corresponding imaging disk, such as percentage, speed, remainging time and elapsed time */
	void updateProgress_MT(HDObject* obj, int percentage, double currentSpeed, 
								int remainingTime, int elapsedTime);
	
	/** clean up something stuff*/
	void cleanUpImaging_Map(HDObject* obj);

	/** Wake one disk imaging taskManage whose status is paused or ready*/
	void wakeAnotherImagingTask();

signals:
	void updateCaseDB();

	void imagingPausedDone();
	void ImagingContinuedDone();


private:

	/** Deallocate the memory of the synchronous variable and thread itself*/
	void releaseForMT(HDObject* obj, struct Q_MT_PARAM* param);

	int findItemFromMap(const HDObject* obj);
	int findItemNotUsedFromMap();
	void makeOneRID(const QString& fileName, int imagingType, int hashType, HDObject* obj);

private:
	QMutex	mutex;

	QHash<HDObject*, RunningDisk> runningHDs;

	int runningCount;
	HDObject* copyingHDs[MAX_COPYING_DISKS_THE_SAME_TIME];
	int itemMap[MAX_COPYING_DISKS_THE_SAME_TIME];
	struct Q_MT_BUFFER* mt_buffer[MAX_COPYING_DISKS_THE_SAME_TIME];

	bool willContinueUndone;
	int undoneCount;
	QList<int> imagingTypes, hashTypes;
	QList<QString> caseNos;
	QList<QString> imagingOutputNames, vendorIds, productIds, SNs;
	QList<quint64> mediaSizes;

	friend class HDDuplicator;

};

#endif